
import java.util.*;

/**
 * Clase encargada de manejar la etapa de escritura a memoria.
 */
class WriteBack extends Stage {

    private boolean done;
    public int numInstructions;

    public WriteBack() {
        super();
        done = false;
        numInstructions = 0;
    }

    /**
     * Procesa la instruccion actual.
     * 
     * @see MemoryType
     * @see Instruction
     * @see ListBoxes
     */
    public void step(MemoryType regFile, Vector Instructions, ListBoxes lb, boolean allNOPs) {

        String str;

        if (myInstruction.wbFlush == true) {
            return;
        }

        if (myInstruction.opcode != 0) {
            numInstructions++;
        }

        switch (myInstruction.opcode) {
            case 0:   // NOP
            case 43:  // SW
            case 70:  // BEQ
            case 71:  // BNE
                break;
            default:

                if ((myInstruction.rd != 0) && (myInstruction.opcode != 0)) {
                    if (myInstruction.flush == false) {
                        regFile.putValue(myInstruction.rdValue, myInstruction.rd);
                        if (myInstruction.rd < 10) {
                            str = "R0" + myInstruction.rd + ": " + myInstruction.rdValue;
                        } else {
                            str = "R" + myInstruction.rd + ": " + myInstruction.rdValue;
                        }
                        lb.RF.replaceItem(str, myInstruction.rd);
                    }
                }
        }


        if ((PC == (Instructions.size() - 1)) && allNOPs) {
            done = true;
            lb.Messages.addItem("Programa hecho.", 0);
        }
    }

    /**
     * Regresa un booleano indicando si la ejecucion del programa fue completa.
     */
    public boolean programaHecho() {
        return done;
    }

    /**
     * Regresa una cadena representado la instruccion actual.
     */
    public String toString() {
        String temp;

        if (myInstruction.wbFlush == true) {
            temp = "FLUSHED: \n" + myInstruction + "\n";
            return temp;
        }

        switch (myInstruction.opcode) {
            case 0:  // NOP
                temp = myInstruction + "\n";
                break;
            case 43:  // SW
            case 70:  // BEQ
            case 71:  // BNE
                temp = Integer.toString(PC) + ":\n" + myInstruction + "\n";
                break;
            default:
                if ((myInstruction.rd != 0) && (myInstruction.opcode != 0)) {
                    temp = Integer.toString(PC) + ":\n" + myInstruction + "\n" +
                            "Wrote $" + Integer.toString(myInstruction.rd) +
                            "= " + Integer.toString(myInstruction.rdValue) + "\n";
                } else {
                    temp = Integer.toString(PC) + ":\n" + myInstruction + "\n";
                }

        }
        return temp;
    }

    /**
     * Regresa un entero representando el numero de la instrucion actual.
     *
     */
    public int getNumeroDeInstruc() {
        return numInstructions;
    }
}  
